﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Agility.Web.Models.RegistrationForm;
using System.Globalization;
using System.ComponentModel.DataAnnotations;

namespace Agility.Testing.Web.UserManagement
{
    [TestFixture]
    public class RegistrationDataTest
    {
        RegistrationData regData;

        #region optional setup and tear down methods
        //// Called before the first test to setup the whole fixture
        //[TestFixtureSetUp]
        //public void TestFixtureSetup()
        //{
        //}

        //// Called after the last test to tear down the whole fixture
        //[TestFixtureTearDown]
        //public void TestFixtureTearDown()
        //{
        //}

        //// Called before each test
        [SetUp]
        public void TestSetup()
        {
            this.regData = new RegistrationData();
        }

        //// Called after each test
        //[TearDown]
        //public void TestTearDown()
        //{ 
        //}

        #endregion

        [Test]
        [Category("UnitTest")]
        public void TestAnswer()
        {
            string expected = "This is the answer.";
            string actual;
            this.regData.Answer = expected;
            actual = regData.Answer;
            Assert.AreEqual(expected, actual);
        }

        [Test]
        [Category("UnitTest")]
        public void TestEmail()
        {
            string expected = "some.one@somewhere.com";
            string actual;
            this.regData.Email = expected;
            actual = regData.Email;
            Assert.AreEqual(expected, actual);
        }

        [Test]
        [Category("UnitTest")]
        public void TestFriendlyName()
        {
            string expected = "My Friendly Name";
            string actual;
            this.regData.FriendlyName = expected;
            actual = regData.FriendlyName;
            Assert.AreEqual(expected, actual);
        }

        [Test]
        [Category("UnitTest")]
        public void TestQuestion()
        {
            string expected = "This is the question";
            string actual;
            this.regData.Question = expected;
            actual = regData.Question;
            Assert.AreEqual(expected, actual);
        }

        [Test]
        [Category("UnitTest")]
        public void TestUserName()
        {
            string expected = "Username";
            string actual;
            this.regData.UserName = expected;
            actual = regData.UserName;
            Assert.AreEqual(expected, actual);
        }

        // compare http://bradwilson.typepad.com/blog/2009/04/dataannotations-and-aspnet-mvc.html for testing for validation attributes

        [Test]
        [Category("UnitTest")]
        [TestCase("UserName", TestName="UserName")]
        [TestCase("Email", TestName="Email")]
        [TestCase("Question", TestName="SecurityQuestion")]
        [TestCase("Answer", TestName="Answer")]
        public void TestRequiredAttribute(string propertyName)
        {
            // Arrange
            var target = typeof(RegistrationData).GetProperty(propertyName);
            var actual = target.GetCustomAttributes(typeof(RequiredAttribute), false)
                                        .Cast<RequiredAttribute>()
                                        .FirstOrDefault();
            string message = string.Format(CultureInfo.InvariantCulture, "RequiredAttribute is missing on RegistrationData.{0}", propertyName);

            // Assert
            Assert.NotNull(actual, message);
        }
        
        [Test]
        [Category("UnitTest")]
        [TestCase("UserName", 4, 255, TestName="UserName")]
        [TestCase("FriendlyName", 0, 255, TestName="FriendlyName")]
        [TestCase("Answer", 0, 128, TestName="Answer")]
        public void TestStringLengthAttribute(string propertyName, int expectedMinimumLength, int expectedMaximumLength)
        {
            // Arrange
            var target = typeof(RegistrationData).GetProperty(propertyName);
            var actual = target.GetCustomAttributes(typeof(StringLengthAttribute), false)
                                                    .Cast<StringLengthAttribute>()
                                                    .FirstOrDefault();
            string isMissingMessage = string.Format(CultureInfo.InvariantCulture, "StringLengthAttribute is missing on RegistrationData.{0}", propertyName);
            string minimumLengthMessage = string.Format(CultureInfo.InvariantCulture, "MinimumLengthAttribute is not set correctly on RegistrationData.{0}", propertyName);
            string maximumLengthMessage = string.Format(CultureInfo.InvariantCulture, "MaximumLengthAttribute is not set correctly on RegistrationData.{0}", propertyName); 

            // Assert
            Assert.NotNull(actual, isMissingMessage);
            Assert.AreEqual(expectedMinimumLength, actual.MinimumLength, minimumLengthMessage);
            Assert.AreEqual(expectedMaximumLength, actual.MaximumLength, maximumLengthMessage);
        }

        [Test]
        [Category("UnitTest")]
        [TestCase("UserName", "^[a-zA-Z0-9_\\-]*$", TestName="UserName")]
        [TestCase("Email", @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$", TestName="Email")]
        public void TestRegularExpressionAttribute(string propertyName, string expected)
        {
            // Arrange
            var target = typeof(RegistrationData).GetProperty(propertyName);
            var actual = target.GetCustomAttributes(typeof(RegularExpressionAttribute), false)
                                                    .Cast<RegularExpressionAttribute>()
                                                    .FirstOrDefault();
            string isMissingMessage = string.Format(CultureInfo.InvariantCulture, "RegularExpressionAttribute is missing on RegistrationData.{0}", propertyName);
            string patternMatchMessage = string.Format(CultureInfo.InvariantCulture, "RegularExpression pattern does not match for RegistrationData.{0}", propertyName);

            // Assert
            Assert.NotNull(actual, isMissingMessage);
            Assert.AreEqual(expected, actual.Pattern, patternMatchMessage);
        }
                        
    }

}
